// --------------------------------------------------------------------------------------------------------------------
// <copyright file="URDataPackagesDefinitions.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Microsoft.Robotics.Hardware.UniversalRobots
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;

    using Microsoft.Robotics.Numerics;

    /// <summary>
    /// Structure to contain a Robot State package type from the UR arm
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct RobotModePackage
    {
        /// <summary>
        /// Speed at which the arm is running as a percentage
        /// </summary>
        public double SpeedFraction;

        /// <summary>
        /// Robot mode
        /// </summary>
        public byte RobotMode;

        /// <summary>
        /// Is the program paused
        /// </summary>
        public byte IsProgramPaused;

        /// <summary>
        /// Is the program running
        /// </summary>
        public byte IsProgramRunning;

        /// <summary>
        /// Is the robot security stopped
        /// </summary>
        public byte IsSecurityStopped;

        /// <summary>
        /// Is the emergency stop engaged
        /// </summary>
        public byte IsEmergencyStopped;

        /// <summary>
        /// Is the robot power on
        /// </summary>
        public byte IsRobotPowerOn;

        /// <summary>
        /// Is the real robot enabled
        /// </summary>
        public byte IsRealRobotEnabled;

        /// <summary>
        /// Is the robot connected
        /// </summary>
        public byte IsPhysicalRobotConnected;

        /// <summary>
        /// Timestamp of packet
        /// </summary>
        public ulong Timestamp;
    }

    /// <summary>
    /// Joint Information
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct JointDataStruct
    {
        /// <summary>
        /// Mode which the joint is in
        /// </summary>
        public byte Mode;

        /// <summary>
        /// Obsolete don't use
        /// </summary>
        public float TMicro;

        /// <summary>
        /// Temperature of the joint motor
        /// </summary>
        public float MotorTempInDegC;

        /// <summary>
        /// Voltage of the joint
        /// </summary>
        public float Voltage;

        /// <summary>
        /// Current of the joint
        /// </summary>
        public float CurrentInAmps;

        /// <summary>
        /// Speed of the joint
        /// </summary>
        public double SpeedInRadPerSec;

        /// <summary>
        /// Target joint position
        /// </summary>
        public double TargetPositionInRadians;

        /// <summary>
        /// Actual joint position
        /// </summary>
        public double AcutalPositionInRadians;
    }

    /// <summary>
    /// Package receive by UR arm for tool data
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct ToolDataPackage
    {
        /// <summary>
        /// Tool mode
        /// </summary>
        public byte ToolMode;

        /// <summary>
        /// Tool temperature
        /// </summary>
        public float ToolTemperature;

        /// <summary>
        /// Tool current
        /// </summary>
        public float ToolCurrent;

        /// <summary>
        /// Tool output voltage
        /// </summary>
        public byte ToolOutputVoltage;

        /// <summary>
        /// Tool voltage 48V?
        /// </summary>
        public float ToolVoltage48V;

        /// <summary>
        /// Analog input 3
        /// </summary>
        public double AnalogInput3;

        /// <summary>
        /// Analog input 2
        /// </summary>
        public double AnalogInput2;

        /// <summary>
        /// Analog input range 3
        /// </summary>
        public byte AnalogInputRange3;

        /// <summary>
        /// Analog input range 2
        /// </summary>
        public byte AnalogInputRange2;
    }

    /// <summary>
    /// Master board Data package received from UR arm.  Assumes Euromap67 is not installed.
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct MasterboardDataPackage
    {
        /// <summary>
        /// Is Euromap67Installed
        /// </summary>
        public byte Euromap67Installed;

        /// <summary>
        /// Master on off state
        /// </summary>
        public byte MasterOnOffState;

        /// <summary>
        /// Master Safety State
        /// </summary>
        public byte MasterSafetyState;

        /// <summary>
        /// Master IO Current
        /// </summary>
        public float MasterIOCurrent;

        /// <summary>
        /// Robot Current
        /// </summary>
        public float RobotCurrent;

        /// <summary>
        /// Robot Voltage 48 V
        /// </summary>
        public float RobotVoltage48V;

        /// <summary>
        /// Master board Temperature
        /// </summary>
        public float MasterboardTemperature;

        /// <summary>
        /// Analog Output1
        /// </summary>
        public double AnalogOutput1;

        /// <summary>
        /// Analog Output 0
        /// </summary>
        public double AnalogOutput0;

        /// <summary>
        /// Analog Output Domain 1
        /// </summary>
        public byte AnalogOutputDomain1;

        /// <summary>
        /// Analog Output Domain 0
        /// </summary>
        public byte AnalogOutputDomain0;

        /// <summary>
        /// Analog Input 1
        /// </summary>
        public double AnalogInput1;

        /// <summary>
        /// Analog Input 0
        /// </summary>
        public double AnalogInput0;

        /// <summary>
        /// Analog Input Range 1
        /// </summary>
        public byte AnalogInputRange1;

        /// <summary>
        /// Analog Input Range 0
        /// </summary>
        public byte AnalogInputRange0;

        /// <summary>
        /// Digital Output Bits
        /// </summary>
        public short DigitalOutputBits;

        /// <summary>
        /// Digital Input Bits
        /// </summary>
        public short DigitalInputBits;
    }

    /// <summary>
    /// Package that contains Cartesian information about the end effector
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct CartesianInfoPackage
    {
        /// <summary>
        /// Rotation around Z
        /// </summary>
        public double Rz;

        /// <summary>
        /// Rotation around Y
        /// </summary>
        public double Ry;

        /// <summary>
        /// Rotation around X
        /// </summary>
        public double Rx;

        /// <summary>
        /// Translation in Z
        /// </summary>
        public double Z;

        /// <summary>
        /// Translation in Y
        /// </summary>
        public double Y;

        /// <summary>
        /// Translation in X
        /// </summary>
        public double X;
    }

    /// <summary>
    /// Robot configuration data
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct ConfigurationDataPackage
    {
        /// <summary>
        /// Motor type, has values 1 or 2.
        /// </summary>
        public int Motor5Type;

        /// <summary>
        /// Motor type, has values 1 or 2.
        /// </summary>
        public int Motor4Type;

        /// <summary>
        /// Motor type, has values 1 or 2.
        /// </summary>
        public int Motor3Type;

        /// <summary>
        /// Motor type, has values 1 or 2.
        /// </summary>
        public int Motor2Type;

        /// <summary>
        /// Motor type, has values 1 or 2.
        /// </summary>
        public int Motor1Type;

        /// <summary>
        /// Motor type, has values 1 or 2.
        /// </summary>
        public int Motor0Type;

        /// <summary>
        /// Robot Sub Type
        /// </summary>
        public int RobotSubType;
        
        /// <summary>
        /// Robot Type
        /// </summary>
        public int RobotType;

        /// <summary>
        /// Controller Box Type
        /// </summary>
        public int ControllerBoxType;

        /// <summary>
        /// Master board Version
        /// </summary>
        public int MasterboardVersion;

        /// <summary>
        /// DH parameter 'theta' for joint 5
        /// </summary>
        public double DHtheta5;

        /// <summary>
        /// DH parameter 'theta' for joint 4
        /// </summary>
        public double DHtheta4;

        /// <summary>
        /// DH parameter 'theta' for joint 3
        /// </summary>
        public double DHtheta3;

        /// <summary>
        /// DH parameter 'theta' for joint 2
        /// </summary>
        public double DHtheta2;

        /// <summary>
        /// DH parameter 'theta' for joint 1
        /// </summary>
        public double DHtheta1;

        /// <summary>
        /// DH parameter 'theta' for joint 0
        /// </summary>
        public double DHtheta0;

        /// <summary>
        /// DH parameter 'alpha' for joint 5
        /// </summary>
        public double DHalpha5;

        /// <summary>
        /// DH parameter 'alpha' for joint 4
        /// </summary>
        public double DHalpha4;

        /// <summary>
        /// DH parameter 'alpha' for joint 3
        /// </summary>
        public double DHalpha3;

        /// <summary>
        /// DH parameter 'alpha' for joint 2
        /// </summary>
        public double DHalpha2;

        /// <summary>
        /// DH parameter 'alpha' for joint 1
        /// </summary>
        public double DHalpha1;

        /// <summary>
        /// DH parameter 'alpha' for joint 0
        /// </summary>
        public double DHalpha0;

        /// <summary>
        /// DH parameter 'd' for joint 5
        /// </summary>
        public double DHd5;

        /// <summary>
        /// DH parameter 'd' for joint 4
        /// </summary>
        public double DHd4;

        /// <summary>
        /// DH parameter 'd' for joint 3
        /// </summary>
        public double DHd3;

        /// <summary>
        /// DH parameter 'd' for joint 2
        /// </summary>
        public double DHd2;

        /// <summary>
        /// DH parameter 'd' for joint 1
        /// </summary>
        public double DHd1;

        /// <summary>
        /// DH parameter 'd' for joint 0
        /// </summary>
        public double DHd0;

        /// <summary>
        /// DH parameter 'a' for joint 5
        /// </summary>
        public double DHa5;

        /// <summary>
        /// DH parameter 'a' for joint 4
        /// </summary>
        public double DHa4;

        /// <summary>
        /// DH parameter 'a' for joint 3
        /// </summary>
        public double DHa3;

        /// <summary>
        /// DH parameter 'a' for joint 2
        /// </summary>
        public double DHa2;

        /// <summary>
        /// DH parameter 'a' for joint 1
        /// </summary>
        public double DHa1;

        /// <summary>
        /// DH parameter 'a' for joint 0
        /// </summary>
        public double DHa0;

        /// <summary>
        /// The characteristic size of the tool
        /// </summary>
        public double EqRadius;

        /// <summary>
        /// Default tool acceleration limit
        /// </summary>
        public double AToolDefault;

        /// <summary>
        /// Default tool speed limit
        /// </summary>
        public double VToolDefault;

        /// <summary>
        /// Default acceleration limit
        /// </summary>
        public double AJointDefault;

        /// <summary>
        /// Default speed limit
        /// </summary>
        public double VJointDefault;

        /// <summary>
        /// Joint Max Acceleration
        /// </summary>
        public double Joint5MaxAcceleration;

        /// <summary>
        /// Joint Max Speed
        /// </summary>
        public double Joint5MaxSpeed;

        /// <summary>
        /// Joint Max Acceleration
        /// </summary>
        public double Joint4MaxAcceleration;

        /// <summary>
        /// Joint Max Speed
        /// </summary>
        public double Joint4MaxSpeed;

        /// <summary>
        /// Joint Max Acceleration
        /// </summary>
        public double Joint3MaxAcceleration;

        /// <summary>
        /// Joint Max Speed
        /// </summary>
        public double Joint3MaxSpeed;

        /// <summary>
        /// Joint Max Acceleration
        /// </summary>
        public double Joint2MaxAcceleration;

        /// <summary>
        /// Joint Max Speed
        /// </summary>
        public double Joint2MaxSpeed;

        /// <summary>
        /// Joint Max Acceleration
        /// </summary>
        public double Joint1MaxAcceleration;

        /// <summary>
        /// Joint Max Speed
        /// </summary>
        public double Joint1MaxSpeed;

        /// <summary>
        /// Joint Max Acceleration
        /// </summary>
        public double Joint0MaxAcceleration;

        /// <summary>
        /// Joint Max Speed
        /// </summary>
        public double Joint0MaxSpeed;

        /// <summary>
        /// Joint Max Limit
        /// </summary>
        public double Joint5MaxLimit;

        /// <summary>
        /// Joint Min Limit
        /// </summary>
        public double Joint5MinLimit;

        /// <summary>
        /// Joint Max Limit
        /// </summary>
        public double Joint4MaxLimit;

        /// <summary>
        /// Joint Min Limit
        /// </summary>
        public double Joint4MinLimit;

        /// <summary>
        /// Joint Max Limit
        /// </summary>
        public double Joint3MaxLimit;

        /// <summary>
        /// Joint Min Limit
        /// </summary>
        public double Joint3MinLimit;

        /// <summary>
        /// Joint Max Limit
        /// </summary>
        public double Joint2MaxLimit;

        /// <summary>
        /// Joint Min Limit
        /// </summary>
        public double Joint2MinLimit;

        /// <summary>
        /// Joint Max Limit
        /// </summary>
        public double Joint1MaxLimit;

        /// <summary>
        /// Joint Min Limit
        /// </summary>
        public double Joint1MinLimit;

        /// <summary>
        /// Joint Max Limit
        /// </summary>
        public double Joint0MaxLimit;

        /// <summary>
        /// Joint Min Limit
        /// </summary>
        public double Joint0MinLimit;
    }

    /// <summary>
    /// TCP force data
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct ForceDataPackage
    {
        /// <summary>
        /// TCP dexterity
        /// </summary>
        public double RobotDexterity;

        /// <summary>
        /// Torque around TCP Z axis
        /// </summary>
        public double Rz;

        /// <summary>
        /// Torque around TCP Y axis
        /// </summary>
        public double Ry;

        /// <summary>
        /// Torque around TCP X axis
        /// </summary>
        public double Rx;

        /// <summary>
        /// Force on TCP Z axis
        /// </summary>
        public double Z;

        /// <summary>
        /// Force on TCP Y axis
        /// </summary>
        public double Y;

        /// <summary>
        /// Force on TCP X axis
        /// </summary>
        public double X;
    }

    /// <summary>
    /// Additional info
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct AdditionalInfoPackage
    {
        /// <summary>
        /// Indicates whether or not teach button is enabled.
        /// </summary>
        public byte IsTeachButtonEnabled;

        /// <summary>
        /// Indicates whether or not teach button is pressed.
        /// </summary>
        public byte IsTeachButtonPressed;
    }

    /// <summary>
    /// Real-time data sent by the real-time interface of the UR Controller.
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct RealtimeDataPackage
    {
        /// <summary>
        /// Mode of joint 5
        /// </summary>
        public double JointMode5;

        /// <summary>
        /// Mode of joint 4
        /// </summary>
        public double JointMode4;

        /// <summary>
        /// Mode of joint 3
        /// </summary>
        public double JointMode3;

        /// <summary>
        /// Mode of joint 2
        /// </summary>
        public double JointMode2;

        /// <summary>
        /// Mode of joint 1
        /// </summary>
        public double JointMode1;

        /// <summary>
        /// Mode of joint 0
        /// </summary>
        public double JointMode0;

        /// <summary>
        /// Robot mode
        /// </summary>
        public double RobotMode;

        /// <summary>
        /// UR use only
        /// </summary>
        public double TestValue;

        /// <summary>
        /// Controller real-time thread execution time
        /// </summary>
        public double ControllerTimer;

        /// <summary>
        /// Temperature of motor 5 in deg C
        /// </summary>
        public double MotorTemperature5;

        /// <summary>
        /// Temperature of motor 4 in deg C
        /// </summary>
        public double MotorTemperature4;

        /// <summary>
        /// Temperature of motor 3 in deg C
        /// </summary>
        public double MotorTemperature3;

        /// <summary>
        /// Temperature of motor 2 in deg C
        /// </summary>
        public double MotorTemperature2;

        /// <summary>
        /// Temperature of motor 1 in deg C
        /// </summary>
        public double MotorTemperature1;

        /// <summary>
        /// Temperature of motor 0 in deg C
        /// </summary>
        public double MotorTemperature0;

        /// <summary>
        /// Digital input bits
        /// </summary>
        public double DigitalInputBits;

        /// <summary>
        /// Tool control point velocity rz in rad/s
        /// </summary>
        public double TcpSpeedRZ;

        /// <summary>
        /// Tool control point velocity ry in rad/s
        /// </summary>
        public double TcpSpeedRY;

        /// <summary>
        /// Tool control point velocity rx in rad/s
        /// </summary>
        public double TcpSpeedRX;

        /// <summary>
        /// Tool control point velocity z in m/s
        /// </summary>
        public double TcpSpeedZ;

        /// <summary>
        /// Tool control point velocity y in m/s 
        /// </summary>
        public double TcpSpeedY;

        /// <summary>
        /// Tool control point velocity x in m/s 
        /// </summary>
        public double TcpSpeedX;

        /// <summary>
        /// Tool control point position rz in rad
        /// </summary>
        public double TcpPositionRZ;

        /// <summary>
        /// Tool control point position ry in rad
        /// </summary>
        public double TcpPositionRY;

        /// <summary>
        /// Tool control point position rx in rad
        /// </summary>
        public double TcpPositionRX;

        /// <summary>
        /// Tool control point position z in m
        /// </summary>
        public double TcpPositionZ;

        /// <summary>
        /// Tool control point position y in m 
        /// </summary>   
        public double TcpPositionY;

        /// <summary>
        /// Tool control point position x in m
        /// </summary>   
        public double TcpPositionX;

        /// <summary>
        /// Tool control point force rz in Nm
        /// </summary>
        public double TcpForceRZ;

        /// <summary>
        /// Tool control point force ry in Nm
        /// </summary>
        public double TcpForceRY;

        /// <summary>
        /// Tool control point force rz in Nm
        /// </summary>
        public double TcpForceRX;

        /// <summary>
        /// Tool control point force z in N
        /// </summary>
        public double TcpForceZ;

        /// <summary>
        /// Tool control point force y in N
        /// </summary>
        public double TcpForceY;

        /// <summary>
        /// Tool control point force x in N
        /// </summary>
        public double TcpForceX;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused14;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused13;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused12;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused11;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused10;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused9;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused8;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused7;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused6;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused5;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused4;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused3;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused2;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused1;

        /// <summary>
        /// This is unused.
        /// </summary>
        public double Unused0;

        /// <summary>
        /// Tool acceleration z in m/s^2
        /// </summary>
        public double ToolAccelZ;

        /// <summary>
        /// Tool acceleration y in m/s^2
        /// </summary>
        public double ToolAccelY;

        /// <summary>
        /// Tool acceleration x in m/s^2
        /// </summary>
        public double ToolAccelX;

        /// <summary>
        /// Actual current for joint 5
        /// </summary>
        public double IActual5;

        /// <summary>
        /// Actual current for joint 4
        /// </summary>
        public double IActual4;

        /// <summary>
        /// Actual current for joint 3
        /// </summary>
        public double IActual3;

        /// <summary>
        /// Actual current for joint 2
        /// </summary>
        public double IActual2;

        /// <summary>
        /// Actual current for joint 1
        /// </summary>
        public double IActual1;

        /// <summary>
        /// Actual current for joint 0
        /// </summary>
        public double IActual0;

        /// <summary>
        /// Actual velocity for joint 5 in rad/s
        /// </summary>
        public double QdActual5;

        /// <summary>
        /// Actual velocity for joint 4 in rad/s
        /// </summary>
        public double QdActual4;

        /// <summary>
        /// Actual velocity for joint 3 in rad/s
        /// </summary>
        public double QdActual3;

        /// <summary>
        /// Actual velocity for joint 2 in rad/s
        /// </summary>
        public double QdActual2;

        /// <summary>
        /// Actual velocity for joint 1 in rad/s
        /// </summary>
        public double QdActual1;

        /// <summary>
        /// Actual velocity for joint 0 in rad/s
        /// </summary>
        public double QdActual0;

        /// <summary>
        /// Actual position for joint 5 in rad
        /// </summary>
        public double QActual5;

        /// <summary>
        /// Actual position for joint 4 in rad
        /// </summary>
        public double QActual4;

        /// <summary>
        /// Actual position for joint 3 in rad
        /// </summary>
        public double QActual3;

        /// <summary>
        /// Actual position for joint 2 in rad
        /// </summary>
        public double QActual2;

        /// <summary>
        /// Actual position for joint 1 in rad
        /// </summary>
        public double QActual1;

        /// <summary>
        /// Actual position for joint 0 in rad
        /// </summary>
        public double QActual0;

        /// <summary>
        /// Target torque for joint 5 in Nm
        /// </summary>
        public double TTarget5;

        /// <summary>
        /// Target torque for joint 4 in Nm
        /// </summary>
        public double TTarget4;

        /// <summary>
        /// Target torque for joint 3 in Nm
        /// </summary>
        public double TTarget3;

        /// <summary>
        /// Target torque for joint 2 in Nm
        /// </summary>
        public double TTarget2;

        /// <summary>
        /// Target torque for joint 1 in Nm
        /// </summary>
        public double TTarget1;

        /// <summary>
        /// Target torque for joint 0 in Nm
        /// </summary>
        public double TTarget0;

        /// <summary>
        /// Target current for joint 5 in amps
        /// </summary>
        public double ITarget5;

        /// <summary>
        /// Target current for joint 4 in amps
        /// </summary>
        public double ITarget4;

        /// <summary>
        /// Target current for joint 3 in amps
        /// </summary>
        public double ITarget3;

        /// <summary>
        /// Target current for joint 2 in amps
        /// </summary>
        public double ITarget2;

        /// <summary>
        /// Target current for joint 1 in amps
        /// </summary>
        public double ITarget1;

        /// <summary>
        /// Target current for joint 0 in amps
        /// </summary>
        public double ITarget0;

        /// <summary>
        /// Target acceleration for joint 5 in rad/s^2
        /// </summary>
        public double QddTarget5;

        /// <summary>
        /// Target acceleration for joint 4 in rad/s^2
        /// </summary>
        public double QddTarget4;

        /// <summary>
        /// Target acceleration for joint 3 in rad/s^2
        /// </summary>
        public double QddTarget3;

        /// <summary>
        /// Target acceleration for joint 2 in rad/s^2
        /// </summary>
        public double QddTarget2;

        /// <summary>
        /// Target acceleration for joint 1 in rad/s^2
        /// </summary>
        public double QddTarget1;

        /// <summary>
        /// Target acceleration for joint 0 in rad/s^2
        /// </summary>
        public double QddTarget0;

        /// <summary>
        /// Target velocity for joint 5 in rad/s
        /// </summary>
        public double QdTarget5;

        /// <summary>
        /// Target velocity for joint 4 in rad/s
        /// </summary>
        public double QdTarget4;

        /// <summary>
        /// Target velocity for joint 3 in rad/s
        /// </summary>
        public double QdTarget3;

        /// <summary>
        /// Target velocity for joint 2 in rad/s
        /// </summary>
        public double QdTarget2;

        /// <summary>
        /// Target velocity for joint 1 in rad/s
        /// </summary>
        public double QdTarget1;

        /// <summary>
        /// Target velocity for joint 0 in rad/s
        /// </summary>
        public double QdTarget0;

        /// <summary>
        /// Target position for joint 5 in rad
        /// </summary>
        public double QTarget5;

        /// <summary>
        /// Target position for joint 4 in rad
        /// </summary>
        public double QTarget4;

        /// <summary>
        /// Target position for joint 3 in rad
        /// </summary>
        public double QTarget3;

        /// <summary>
        /// Target position for joint 2 in rad
        /// </summary>
        public double QTarget2;

        /// <summary>
        /// Target position for joint 1 in rad
        /// </summary>
        public double QTarget1;

        /// <summary>
        /// Target position for joint 0 in rad
        /// </summary>
        public double QTarget0;

        /// <summary>
        /// Time since controller start in s
        /// </summary>
        public double Timestamp;

        /// <summary>
        /// Total message length
        /// </summary>
        public int MessageLength;
    }

    /// <summary>
    /// Additional info
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class AdditionalInfo
    {
        /// <summary>
        /// Struct containing additional info
        /// </summary>
        private AdditionalInfoPackage additionalInfoPackage;

        /// <summary>
        /// Initializes a new instance of the <see cref="AdditionalInfo"/> class
        /// </summary>
        /// <param name="additionalInfoPackageBytes">Bytes to be blitted to a <see cref="AdditionalInfoPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>additionalInfoPackageBytes</c> at which package payload begins.</param>
        public AdditionalInfo(byte[] additionalInfoPackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (AdditionalInfoPackage* additionalInfoPackagePtr = &this.additionalInfoPackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(additionalInfoPackagePtr, additionalInfoPackageBytes, sizeof(AdditionalInfoPackage), offset);
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether or not teach button is pressed.
        /// </summary>
        public bool IsTeachButtonPressed
        {
            get
            {
                return (this.additionalInfoPackage.IsTeachButtonPressed != 0);
            }
        }

        /// <summary>
        /// Gets a value indicating whether or not teach button is enabled.
        /// </summary>
        public bool IsTeachButtonEnabled
        {
            get
            {
                return (this.additionalInfoPackage.IsTeachButtonEnabled != 0);
            }
        }
    }
 
    /// <summary>
    /// TCP force data
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class TcpForceData
    {
        /// <summary>
        /// Struct containing force data
        /// </summary>
        private ForceDataPackage forceDataPackage;

        /// <summary>
        /// Initializes a new instance of the <see cref="TcpForceData"/> class
        /// </summary>
        /// <param name="forceDataPackageBytes">Bytes to be blitted to a <see cref="ForceDataPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>forceDataPackageBytes</c> at which package payload begins.</param>
        public TcpForceData(byte[] forceDataPackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (ForceDataPackage* forceDataPackagePtr = &this.forceDataPackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(forceDataPackagePtr, forceDataPackageBytes, sizeof(ForceDataPackage), offset);
                }
            }
        }

        /// <summary>
        /// Gets the force on TCP X axis
        /// </summary>
        public double X
        {
            get
            {
                return this.forceDataPackage.X;
            }
        }

        /// <summary>
        /// Gets the force on TCP Y axis
        /// </summary>
        public double Y
        {
            get
            {
                return this.forceDataPackage.Y;
            }
        }

        /// <summary>
        /// Gets the force on TCP Z axis
        /// </summary>
        public double Z
        {
            get
            {
                return this.forceDataPackage.Z;
            }
        }

        /// <summary>
        /// Gets the torque around TCP X axis
        /// </summary>
        public double Rx
        {
            get
            {
                return this.forceDataPackage.Rx;
            }
        }

        /// <summary>
        /// Gets the torque around TCP Y axis
        /// </summary>
        public double Ry
        {
            get
            {
                return this.forceDataPackage.Ry;
            }
        }

        /// <summary>
        /// Gets the torque around TCP Z axis
        /// </summary>
        public double Rz
        {
            get
            {
                return this.forceDataPackage.Rz;
            }
        }

        /// <summary>
        /// Gets the tCP dexterity
        /// </summary>
        public double RobotDexterity
        {
            get
            {
                return this.forceDataPackage.RobotDexterity;
            }
        }
    }

    /// <summary>
    /// Robot configuration data
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class ConfigurationData
    {
        /// <summary>
        /// Struct containing configuration data
        /// </summary>
        private ConfigurationDataPackage configurationDataPackage;

        /// <summary>
        /// Alpha DH parameter for each joint
        /// </summary>
        private double[] alpha = null;

        /// <summary>
        /// Theta DH parameter for each joint
        /// </summary>
        private double[] theta = null;

        /// <summary>
        /// a DH parameter for each joint
        /// </summary>
        private double[] a = null;

        /// <summary>
        /// d DH parameter for each joint
        /// </summary>
        private double[] d = null;

        /// <summary>
        /// Minimum position limit for each joint
        /// </summary>
        private double[] jointMinLimit = null;

        /// <summary>
        /// Maximum position limit for each joint
        /// </summary>
        private double[] jointMaxLimit = null;

        /// <summary>
        /// Maximum speed for each joint
        /// </summary>
        private double[] jointMaxSpeed = null;

        /// <summary>
        /// Maximum acceleration for each joint
        /// </summary>
        private double[] jointMaxAcceleration = null;

        /// <summary>
        /// Motor type for each joint
        /// </summary>
        private int[] motorType = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="ConfigurationData"/> class
        /// </summary>
        /// <param name="configurationDataPackageBytes">Bytes to be blitted to a <see cref="ConfigurationDataPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>configurationDataPackageBytes</c> at which package payload begins.</param>
        public ConfigurationData(byte[] configurationDataPackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (ConfigurationDataPackage* configurationDataPackagePtr = &this.configurationDataPackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(configurationDataPackagePtr, configurationDataPackageBytes, sizeof(ConfigurationDataPackage), offset);
                }
            }
        }

        /// <summary>
        /// Gets the motor type for each joint
        /// </summary>
        public int[] MotorType
        {
            get
            {
                if (this.motorType == null)
                {
                    this.motorType = new int[]
                    {
                        this.configurationDataPackage.Motor0Type,
                        this.configurationDataPackage.Motor1Type,
                        this.configurationDataPackage.Motor2Type,
                        this.configurationDataPackage.Motor3Type,
                        this.configurationDataPackage.Motor4Type,
                        this.configurationDataPackage.Motor5Type
                    };
                }

                return this.motorType;
            }
        }

        /// <summary>
        /// Gets the alpha DH parameter for each joint
        /// </summary>
        public double[] Alpha
        {
            get
            {
                if (this.alpha == null)
                {
                    this.alpha = new double[]
                    {
                        this.configurationDataPackage.DHalpha0,
                        this.configurationDataPackage.DHalpha1,
                        this.configurationDataPackage.DHalpha2,
                        this.configurationDataPackage.DHalpha3,
                        this.configurationDataPackage.DHalpha4,
                        this.configurationDataPackage.DHalpha5
                    };
                }

                return this.alpha;
            }
        }

        /// <summary>
        /// Gets the theta DH parameter for each joint
        /// </summary>
        public double[] Theta
        {
            get
            {
                if (this.theta == null)
                {
                    this.theta = new double[]
                    {
                        this.configurationDataPackage.DHtheta0,
                        this.configurationDataPackage.DHtheta1,
                        this.configurationDataPackage.DHtheta2,
                        this.configurationDataPackage.DHtheta3,
                        this.configurationDataPackage.DHtheta4,
                        this.configurationDataPackage.DHtheta5
                    };
                }

                return this.theta;
            }
        }

        /// <summary>
        /// Gets the A DH parameter for each joint
        /// </summary>
        public double[] A
        {
            get
            {
                if (this.a == null)
                {
                    this.a = new double[]
                    {
                        this.configurationDataPackage.DHa0,
                        this.configurationDataPackage.DHa1,
                        this.configurationDataPackage.DHa2,
                        this.configurationDataPackage.DHa3,
                        this.configurationDataPackage.DHa4,
                        this.configurationDataPackage.DHa5
                    };
                }

                return this.a;
            }
        }

        /// <summary>
        /// Gets the d DH parameter for each joint
        /// </summary>
        public double[] D
        {
            get
            {
                if (this.d == null)
                {
                    this.d = new double[]
                    {
                        this.configurationDataPackage.DHd0,
                        this.configurationDataPackage.DHd1, this.configurationDataPackage.DHd2,
                        this.configurationDataPackage.DHd3,
                        this.configurationDataPackage.DHd4,
                        this.configurationDataPackage.DHd5,
                    };
                }

                return this.d;
            }
        }

        /// <summary>
        /// Gets the minimum position limit for each joint
        /// </summary>
        public double[] JointMinLimit
        {
            get
            {
                if (this.jointMinLimit == null)
                {
                    this.jointMinLimit = new double[]
                    {
                        this.configurationDataPackage.Joint0MinLimit,
                        this.configurationDataPackage.Joint1MinLimit,
                        this.configurationDataPackage.Joint2MinLimit,
                        this.configurationDataPackage.Joint3MinLimit,
                        this.configurationDataPackage.Joint4MinLimit,
                        this.configurationDataPackage.Joint5MinLimit
                    };
                }

                return this.jointMinLimit;
            }
        }

        /// <summary>
        /// Gets the maximum position limit for each joint
        /// </summary>
        public double[] JointMaxLimit
        {
            get
            {
                if (this.jointMaxLimit == null)
                {
                    this.jointMaxLimit = new double[]
                    {
                        this.configurationDataPackage.Joint0MaxLimit,
                        this.configurationDataPackage.Joint1MaxLimit,
                        this.configurationDataPackage.Joint2MaxLimit,
                        this.configurationDataPackage.Joint3MaxLimit,
                        this.configurationDataPackage.Joint4MaxLimit,
                        this.configurationDataPackage.Joint5MaxLimit
                    };
                }

                return this.jointMaxLimit;
            }
        }

        /// <summary>
        /// Gets the maximum speed for each joint
        /// </summary>
        public double[] JointMaxSpeed
        {
            get
            {
                if (this.jointMaxSpeed == null)
                {
                    this.jointMaxSpeed = new double[]
                    {
                        this.configurationDataPackage.Joint0MaxSpeed,
                        this.configurationDataPackage.Joint1MaxSpeed,
                        this.configurationDataPackage.Joint2MaxSpeed,
                        this.configurationDataPackage.Joint3MaxSpeed,
                        this.configurationDataPackage.Joint4MaxSpeed,
                        this.configurationDataPackage.Joint5MaxSpeed
                    };
                }

                return this.jointMaxSpeed;
            }
        }

        /// <summary>
        /// Gets the maximum acceleration for each joint
        /// </summary>
        public double[] JointMaxAcceleration
        {
            get
            {
                if (this.jointMaxAcceleration == null)
                {
                    this.jointMaxAcceleration = new double[]
                    {
                        this.configurationDataPackage.Joint0MaxAcceleration,
                        this.configurationDataPackage.Joint1MaxAcceleration,
                        this.configurationDataPackage.Joint2MaxAcceleration,
                        this.configurationDataPackage.Joint3MaxAcceleration,
                        this.configurationDataPackage.Joint4MaxAcceleration,
                        this.configurationDataPackage.Joint5MaxAcceleration
                    };
                }

                return this.jointMaxAcceleration;
            }
        }

        /// <summary>
        /// Gets the robot Sub Type
        /// </summary>
        public int RobotSubType
        {
            get
            {
                return this.configurationDataPackage.RobotSubType;
            }
        }

        /// <summary>
        /// Gets the robot Type
        /// </summary>
        public int RobotType
        {
            get
            {
                return this.configurationDataPackage.RobotType;
            }
        }

        /// <summary>
        /// Gets the controller Box Type
        /// </summary>
        public int ControllerBoxType
        {
            get
            {
                return this.configurationDataPackage.ControllerBoxType;
            }
        }

        /// <summary>
        /// Gets the master board Version
        /// </summary>
        public int MasterboardVersion
        {
            get
            {
                return this.configurationDataPackage.MasterboardVersion;
            }
        }

        /// <summary>
        /// Gets the the characteristic size of the tool
        /// </summary>
        public double EqRadius
        {
            get
            {
                return this.configurationDataPackage.EqRadius;
            }
        }

        /// <summary>
        /// Gets the default tool acceleration limit
        /// </summary>
        public double AToolDefault
        {
            get
            {
                return this.configurationDataPackage.AToolDefault;
            }
        }

        /// <summary>
        /// Gets the default tool speed limit
        /// </summary>
        public double VToolDefault
        {
            get
            {
                return this.configurationDataPackage.VToolDefault;
            }
        }

        /// <summary>
        /// Gets the default acceleration limit
        /// </summary>
        public double AJointDefault
        {
            get
            {
                return this.configurationDataPackage.AJointDefault;
            }
        }

        /// <summary>
        /// Gets the default speed limit
        /// </summary>
        public double VJointDefault
        {
            get
            {
                return this.configurationDataPackage.VJointDefault;
            }
        }
    }

    /// <summary>
    /// Cartesian location of end effector
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class CartesianData
    {
        /// <summary>
        /// Struct containing Cartesian data
        /// </summary>
        private CartesianInfoPackage cartesianInfoPackage;

        /// <summary>
        /// Current TCP position
        /// </summary>
        private Pose tcpPosition;

        /// <summary>
        /// Initializes a new instance of the <see cref="CartesianData"/> class
        /// </summary>
        /// <param name="cartesianInfoPackageBytes">Bytes to be blitted to a <see cref="CartesianInfoPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>cartesianInfoPackageBytes</c> at which package payload begins.</param>
        public CartesianData(byte[] cartesianInfoPackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (CartesianInfoPackage* cartesianInfoPackagePtr = &this.cartesianInfoPackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(cartesianInfoPackagePtr, cartesianInfoPackageBytes, sizeof(CartesianInfoPackage), offset);
                }
            }

            Vector3 rotVec = new Vector3(this.cartesianInfoPackage.Rx, this.cartesianInfoPackage.Ry, this.cartesianInfoPackage.Rz);

            double angle = rotVec.Length();

            rotVec = Vector3.Normalize(rotVec);

            this.tcpPosition = new Pose(
                new Vector3(
                    this.cartesianInfoPackage.X,
                    this.cartesianInfoPackage.Y,
                    this.cartesianInfoPackage.Z),
                Quaternion.FromAxisAngle(
                    new AxisAngle(
                        rotVec,
                        angle)));
        }

        /// <summary>
        /// Gets the cartesian pose;
        /// </summary>
        public Pose CartesianPose
        {
            get
            {
                return this.tcpPosition;
            }
        }
    }

    /// <summary>
    /// Master board Data 
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class MasterboardData
    {
        /// <summary>
        /// Struct containing master board data
        /// </summary>
        private MasterboardDataPackage masterboardDataPackage;

        /// <summary>
        /// Initializes a new instance of the <see cref="MasterboardData"/> class
        /// </summary>
        /// <param name="masterboardDataPackageBytes">Bytes to be blitted to a <see cref="MasterboardDataPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>masterboardDataPackageBytes</c> at which package payload begins.</param>
        public MasterboardData(byte[] masterboardDataPackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (MasterboardDataPackage* masterboardDataPackagePtr = &this.masterboardDataPackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(masterboardDataPackagePtr, masterboardDataPackageBytes, sizeof(MasterboardDataPackage), offset);
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether Euromap67 is installed.
        /// </summary>
        public bool IsEuromap67Installed
        {
            get
            {
                return (this.masterboardDataPackage.Euromap67Installed != 0);
            }
        }

        /// <summary>
        /// Gets the master on off state
        /// </summary>
        public byte MasterOnOffState
        {
            get
            {
                return this.masterboardDataPackage.MasterOnOffState;
            }
        }

        /// <summary>
        /// Gets the master Safety State
        /// </summary>
        public byte MasterSafetyState
        {
            get
            {
                return this.masterboardDataPackage.MasterSafetyState;
            }
        }

        /// <summary>
        /// Gets the master IO Current
        /// </summary>
        public float MasterIOCurrent
        {
            get
            {
                return this.masterboardDataPackage.MasterIOCurrent;
            }
        }

        /// <summary>
        /// Gets the robot Current
        /// </summary>
        public float RobotCurrent
        {
            get
            {
                return this.masterboardDataPackage.RobotCurrent;
            }
        }

        /// <summary>
        /// Gets the robot Voltage 48 V
        /// </summary>
        public float RobotVoltage48V
        {
            get
            {
                return this.masterboardDataPackage.RobotVoltage48V;
            }
        }

        /// <summary>
        /// Gets the master board Temperature
        /// </summary>
        public float MasterboardTemperature
        {
            get
            {
                return this.masterboardDataPackage.MasterboardTemperature;
            }
        }

        /// <summary>
        /// Gets the analog Output1
        /// </summary>
        public double AnalogOutput1
        {
            get
            {
                return this.masterboardDataPackage.AnalogOutput1;
            }
        }

        /// <summary>
        /// Gets the analog Output 0
        /// </summary>
        public double AnalogOutput0
        {
            get
            {
                return this.masterboardDataPackage.AnalogOutput0;
            }
        }

        /// <summary>
        /// Gets the analog Output Domain 1
        /// </summary>
        public byte AnalogOutputDomain1
        {
            get
            {
                return this.masterboardDataPackage.AnalogOutputDomain1;
            }
        }

        /// <summary>
        /// Gets the analog Output Domain 0
        /// </summary>
        public byte AnalogOutputDomain0
        {
            get
            {
                return this.masterboardDataPackage.AnalogOutputDomain0;
            }
        }

        /// <summary>
        /// Gets the analog Input 1
        /// </summary>
        public double AnalogInput1
        {
            get
            {
                return this.masterboardDataPackage.AnalogInput1;
            }
        }

        /// <summary>
        /// Gets the analog Input 0
        /// </summary>
        public double AnalogInput0
        {
            get
            {
                return this.masterboardDataPackage.AnalogInput0;
            }
        }

        /// <summary>
        /// Gets the analog Input Range 1
        /// </summary>
        public byte AnalogInputRange1
        {
            get
            {
                return this.masterboardDataPackage.AnalogInputRange1;
            }
        }

        /// <summary>
        /// Gets the analog Input Range 0
        /// </summary>
        public byte AnalogInputRange0
        {
            get
            {
                return this.masterboardDataPackage.AnalogInputRange0;
            }
        }

        /// <summary>
        /// Gets the digital Output Bits
        /// </summary>
        public short DigitalOutputBits
        {
            get
            {
                return this.masterboardDataPackage.DigitalOutputBits;
            }
        }

        /// <summary>
        /// Gets the digital Input Bits
        /// </summary>
        public short DigitalInputBits
        {
            get
            {
                return this.masterboardDataPackage.DigitalInputBits;
            }
        }
    }

    /// <summary>
    /// Data regarding tool.
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class ToolData
    {
        /// <summary>
        /// Struct containing tool data package data
        /// </summary>
        private ToolDataPackage toolDataPackage;

        /// <summary>
        /// Initializes a new instance of the <see cref="ToolData"/> class
        /// </summary>
        /// <param name="toolDataPackageBytes">Bytes to be blitted to a <see cref="ToolDataPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>toolDataPackageBytes</c> at which package payload begins.</param>
        public ToolData(byte[] toolDataPackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (ToolDataPackage* toolDataPackagePtr = &this.toolDataPackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(toolDataPackagePtr, toolDataPackageBytes, sizeof(ToolDataPackage), offset);
                }
            }
        }

        /// <summary>
        /// Gets the tool mode
        /// </summary>
        public byte ToolMode
        {
            get
            {
                return this.toolDataPackage.ToolMode;
            }
        }

        /// <summary>
        /// Gets the tool temperature
        /// </summary>
        public float ToolTemperature
        {
            get
            {
                return this.toolDataPackage.ToolTemperature;
            }
        }

        /// <summary>
        /// Gets the tool current
        /// </summary>
        public float ToolCurrent
        {
            get
            {
                return this.toolDataPackage.ToolCurrent;
            }
        }

        /// <summary>
        /// Gets the tool output voltage
        /// </summary>
        public byte ToolOutputVoltage
        {
            get
            {
                return this.toolDataPackage.ToolOutputVoltage;
            }
        }

        /// <summary>
        /// Gets the tool voltage 48V?
        /// </summary>
        public float ToolVoltage48V
        {
            get
            {
                return this.toolDataPackage.ToolVoltage48V;
            }
        }

        /// <summary>
        /// Gets the analog input 3
        /// </summary>
        public double AnalogInput3
        {
            get
            {
                return this.toolDataPackage.AnalogInput3;
            }
        }

        /// <summary>
        /// Gets the analog input 2
        /// </summary>
        public double AnalogInput2
        {
            get
            {
                return this.toolDataPackage.AnalogInput2;
            }
        }

        /// <summary>
        /// Gets the analog input range 3
        /// </summary>
        public byte AnalogInputRange3
        {
            get
            {
                return this.toolDataPackage.AnalogInputRange3;
            }
        }

        /// <summary>
        /// Gets the analog input range 2
        /// </summary>
        public byte AnalogInputRange2
        {
            get
            {
                return this.toolDataPackage.AnalogInputRange2;
            }
        }
    }

    /// <summary>
    /// Object that wraps a RobotModePackage (renamed controller data as there is actually a lot more than robot mode here)
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class ControllerData
    {
        /// <summary>
        /// Struct containing robot mode package data
        /// </summary>
        private RobotModePackage robotModePackage;

        /// <summary>
        /// Initializes a new instance of the <see cref="ControllerData"/> class
        /// </summary>
        /// <param name="robotModePackageBytes">Bytes to be blitted to a <see cref="RobotModePackage"/> struct.</param>
        /// <param name="offset">Offset into <c>robotModePackageBytes</c> at which package payload begins.</param>
        public ControllerData(byte[] robotModePackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (RobotModePackage* robotModePackagePtr = &this.robotModePackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(robotModePackagePtr, robotModePackageBytes, sizeof(RobotModePackage), offset);
                }
           }
        }

        /// <summary>
        /// Gets the speed at which the arm is running as a percentage
        /// </summary>
        public double SpeedFraction
        {
            get
            {
                return this.robotModePackage.SpeedFraction;
            }
        }

        /// <summary>
        /// Gets the robot mode
        /// </summary>
        public URDataPackages.RobotModes RobotMode
        {
            get
            {
                return (URDataPackages.RobotModes)this.robotModePackage.RobotMode;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the program paused
        /// </summary>
        public bool IsProgramPaused
        {
            get
            {
                return (this.robotModePackage.IsProgramPaused != 0);
            }
        }

        /// <summary>
        /// Gets a value indicating whether the program running
        /// </summary>
        public bool IsProgramRunning
        {
            get
            {
                return (this.robotModePackage.IsProgramRunning != 0);
            }
        }

        /// <summary>
        /// Gets a value indicating whether the robot security stopped
        /// </summary>
        public bool IsSecurityStopped
        {
            get
            {
                return (this.robotModePackage.IsSecurityStopped != 0);
            }
        }

        /// <summary>
        /// Gets a value indicating whether the emergency stop engaged
        /// </summary>
        public bool IsEmergencyStopped
        {
            get
            {
                return (this.robotModePackage.IsEmergencyStopped != 0);
            }
        }

        /// <summary>
        /// Gets a value indicating whether the robot power on
        /// </summary>
        public bool IsRobotPowerOn
        {
            get
            {
                return (this.robotModePackage.IsRobotPowerOn != 0);
            }
        }

        /// <summary>
        /// Gets a value indicating whether the real robot enabled
        /// </summary>
        public bool IsRealRobotEnabled
        {
            get
            {
                return (this.robotModePackage.IsRealRobotEnabled != 0);
            }
        }

        /// <summary>
        /// Gets a value indicating whether the robot connected
        /// </summary>
        public bool IsPhysicalRobotConnected
        {
            get
            {
                return (this.robotModePackage.IsPhysicalRobotConnected != 0);
            }
        }

        /// <summary>
        /// Gets the timestamp of packet
        /// </summary>
        public ulong Timestamp
        {
            get
            {
                return this.robotModePackage.Timestamp;
            }
        }
    }

    /// <summary>
    /// Object that wraps a JointDataPackage
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class JointChainData
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="JointChainData"/> class
        /// </summary>
        /// <param name="jointDataPackageBytes">Bytes to be blitted to a <see cref="JointDataPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>jointDataPackageBytes</c> at which package payload begins.</param>
        /// <param name="numJoints">Number of joints in chain.</param>
        public JointChainData(byte[] jointDataPackageBytes, int offset = 0, int numJoints = 6)
        {
            this.JointData = new JointData[numJoints];

            unsafe
            {
                for (int i = 0; i < numJoints; ++i)
                {
                    this.JointData[i] = new JointData(jointDataPackageBytes, i * sizeof(JointDataStruct) + offset, i);
                }
            }
        }

        /// <summary>
        /// Gets the value of the <see cref="JointDataPackage"/>
        /// </summary>
        public JointData[] JointData { get; private set; }
    }

    /// <summary>
    /// Data for an individual joint
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class JointData
    {
        /// <summary>
        /// Struct holding the joint data
        /// </summary>
        private JointDataStruct jointDataStruct;

        /// <summary>
        /// Initializes a new instance of the <see cref="JointData"/> class.
        /// </summary>
        /// <param name="jointDataPackageBytes">Bytes comprising the joint data package.</param>
        /// <param name="offset">Offset into the byte array to start parsing at.</param>
        /// <param name="jointNumber">Joint number.</param>
        [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
        public JointData(byte[] jointDataPackageBytes, int offset, int jointNumber)
        {
            unsafe
            {
                fixed (JointDataStruct* jointDataStructPtr = &this.jointDataStruct)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(
                        jointDataStructPtr,
                        jointDataPackageBytes,
                        sizeof(JointDataStruct),
                        offset);
                }
           }

            this.JointNumber = jointNumber;
        }

        /// <summary>
        /// Gets the joint number
        /// </summary>
        public int JointNumber { get; private set; }

        /// <summary>
        /// Gets the mode which the joint is in
        /// </summary>
        public URDataPackages.JointModes Mode
        {
            get
            {
                return (URDataPackages.JointModes)this.jointDataStruct.Mode;
            }
        }

        /// <summary>
        /// Gets the obsolete don't use
        /// </summary>
        public float TMicro
        {
            get
            {
                return this.jointDataStruct.TMicro;
            }
        }

        /// <summary>
        /// Gets the temperature of the joint motor
        /// </summary>
        public float MotorTempInDegC
        {
            get
            {
                return this.jointDataStruct.MotorTempInDegC;
            }
        }

        /// <summary>
        /// Gets the voltage of the joint
        /// </summary>
        public float Voltage
        {
            get
            {
                return this.jointDataStruct.Voltage;
            }
        }

        /// <summary>
        /// Gets the current of the joint
        /// </summary>
        public float CurrentInAmps
        {
            get
            {
                return this.jointDataStruct.CurrentInAmps;
            }
        }

        /// <summary>
        /// Gets the speed of the joint
        /// </summary>
        public double SpeedInRadPerSec
        {
            get
            {
                return this.jointDataStruct.SpeedInRadPerSec;
            }
        }

        /// <summary>
        /// Gets the target joint position
        /// </summary>
        public double TargetPositionInRadians
        {
            get
            {
                return this.jointDataStruct.TargetPositionInRadians;
            }
        }

        /// <summary>
        /// Gets the actual joint position
        /// </summary>
        public double ActualPositionInRadians
        {
            get
            {
                return this.jointDataStruct.AcutalPositionInRadians;
            }
        }
    }

    /// <summary>
    /// Object that wraps a <c>RealtimeDataPackage</c> struct
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "File contains relatively simple and very similar classes.")]
    public class RealtimeData
    {
        /// <summary>
        /// Struct containing real-time package data
        /// </summary>
        private RealtimeDataPackage realtimeDataPackage;

        /// <summary>
        /// Initializes a new instance of the <see cref="RealtimeData"/> class
        /// </summary>
        /// <param name="realtimeDataPackageBytes">Bytes to be blitted to a <see cref="RealtimeDataPackage"/> struct.</param>
        /// <param name="offset">Offset into <c>realtimeDataPackageBytes</c> at which package payload begins.</param>
        public RealtimeData(byte[] realtimeDataPackageBytes, int offset = 0)
        {
            unsafe
            {
                fixed (RealtimeDataPackage* realtimeDataPackagePtr = &this.realtimeDataPackage)
                {
                    URDataByteOperations.CopyByteArrayToStructPointer(realtimeDataPackagePtr, realtimeDataPackageBytes, sizeof(RealtimeDataPackage), offset);
                }
           }
        }

        /// <summary>
        /// Gets the raw real-time data struct
        /// </summary>
        public RealtimeDataPackage RealtimeDataPackage
        {
            get
            {
                return this.realtimeDataPackage;
            }
        }
    }
}
